package com.qzyh.esb.egsa.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qzyh.esb.egsa.entity.MessageHeader;
import com.qzyh.esb.egsa.entity.MessageHeaderField;
import com.qzyh.esb.egsa.entity.RoleMenu;
import com.qzyh.esb.egsa.entity.User;
import com.qzyh.esb.egsa.mapper.MessageHeaderFieldMapper;
import com.qzyh.esb.egsa.mapper.MessageHeaderMapper;
import com.qzyh.esb.egsa.service.IMessageHeaderService;
import com.qzyh.esb.egsa.utils.FillUtil;
import com.qzyh.esb.egsa.utils.ResultObject;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 报文头信息表 服务实现类
 * </p>
 *
 * @author whq
 * @since 2023-11-02
 */
@Service
public class MessageHeaderServiceImpl extends ServiceImpl<MessageHeaderMapper, MessageHeader> implements IMessageHeaderService {

    private static final Logger logger = LoggerFactory.getLogger(MessageHeaderServiceImpl.class);

    @Autowired
    private MessageHeaderMapper messageHeaderMapper;

    @Autowired
    private MessageHeaderFieldMapper messageHeaderFieldMapper;

    @Override
    public IPage<MessageHeader> getList(IPage<MessageHeader> page, String name) {
        QueryWrapper<MessageHeader> wrapper = Wrappers.query();
        if (StringUtils.hasLength(name)) {
            wrapper.like("name", name);
        }
        wrapper.orderByDesc("create_time");
        return messageHeaderMapper.selectPage(page, wrapper);
    }

    @Override
    @Transactional
    public ResultObject parseFile(MultipartFile file, String id) {
        //判断该报文头id是否存在
        MessageHeader messageHeader = messageHeaderMapper.selectById(id);
        if (messageHeader == null)
            return ResultObject.fail("报文头主键不存在，请联系管理员！");
        //修改报文头的更新时间
        messageHeader = (MessageHeader) FillUtil.fill(messageHeader);
        messageHeaderMapper.updateById(messageHeader);
        //获取报文头文件的内容
        List<String> excelContentList = getFileContent(file);
        //解析报文头文件为实体
        List<MessageHeaderField> messageHeaderFieldList =  parseExcelToField(excelContentList, id);
        //清空原先的报文头字段
        QueryWrapper<MessageHeaderField> messageHeaderFieldQueryWrapper = Wrappers.query();
        messageHeaderFieldQueryWrapper.eq("message_header_id", id);
        messageHeaderFieldMapper.delete(messageHeaderFieldQueryWrapper);
        //插入新的报文头字段
        for (int i = 0; i < messageHeaderFieldList.size(); i++) {
            messageHeaderFieldMapper.insert(messageHeaderFieldList.get(i));
        }
        return ResultObject.success("报文头文件修改成功");
    }

    @Override
    public ResultObject<List<MessageHeaderField>> getMsgHeaderFieldById(String id) {
        List<MessageHeaderField> result = new ArrayList<>();
        //获取报文头输入字段
        result.addAll(getMsgHeaderFieldList(id,"req"));
        //获取报文头输出字段
        result.addAll(getMsgHeaderFieldList(id,"rsp"));
        return ResultObject.success("查询成功",result);
    }

    @Override
    public String getFileNameById(String id) {
        MessageHeader messageHeader =  messageHeaderMapper.selectById(id);
        if (messageHeader != null)
            return messageHeader.getName();
        return null;
    }

    @Override
    public XSSFWorkbook genExcel(String id) {
        XSSFWorkbook wb = null;
        try {
            wb = new XSSFWorkbook();
            XSSFSheet sheet = wb.createSheet();
            //设置表头
            //设置第一行和第二行
            sheet = setFirstAndSecondRow(wb,sheet);
            //设置输入行
            sheet = setInputOrOutputRow(wb,sheet,3,"输入");
            //设置输入字段
            List<MessageHeaderField> result = getMsgHeaderFieldList(id,"req");
            //获取报文头输入字段
            //设置输出行
            //设置输出字段

        } catch (Exception e) {
            e.printStackTrace();
        }
        return wb;
    }

    private XSSFSheet setInputOrOutputRow(XSSFWorkbook wb, XSSFSheet sheet, int rowNum, String value) {
        XSSFRow row = sheet.createRow(rowNum);
        for (int i = 0; i < 13; i++) {
            // 创建单元格
            XSSFCell cell = row.createCell(i);
            if (i==0)
                cell.setCellValue(value);
        }
        sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 12));
        return sheet;
    }

    private XSSFSheet setFirstAndSecondRow(XSSFWorkbook wb, XSSFSheet sheet) {
        // 创建单元格风格样式
        XSSFCellStyle cellStyle = wb.createCellStyle();
        // 设置样式-单元格边框
        cellStyle.setBorderBottom(BorderStyle.THIN);
        cellStyle.setBorderLeft(BorderStyle.THIN);
        cellStyle.setBorderRight(BorderStyle.THIN);
        cellStyle.setBorderTop(BorderStyle.THIN);
        cellStyle.setAlignment(HorizontalAlignment.CENTER);
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        cellStyle.setWrapText(true);
        // 创建行数据
        XSSFRow row1 = sheet.createRow(0);
        for (int i = 0; i < 13; i++) {
            // 创建单元格
            XSSFCell cell = row1.createCell(i);
            if (i==0)
                cell.setCellValue("原始接口");
            else if (i==7)
                cell.setCellValue("QZBSD");
            cell.setCellStyle(cellStyle);
        }
        sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 5));
        sheet.addMergedRegion(new CellRangeAddress(0, 0, 7, 12));

        // 创建第二行数据
        XSSFRow row2 = sheet.createRow(1);
        String[] arr = {"英文名称","中文名称","数据类型","长度","是否必输","备注","","英文名称","中文名称","数据类型(长度)","约束条件","是否必输","备注"};
        for (int i = 0; i < 13; i++) {
            // 创建单元格
            XSSFCell cell = row2.createCell(i);
            cell.setCellValue(arr[i]);
            cell.setCellStyle(cellStyle);
        }
        return sheet;
    }

    private List<MessageHeaderField> getMsgHeaderFieldList(String id, String type){
        List<MessageHeaderField> list = new ArrayList<>();
        MessageHeaderField messageHeaderField = new MessageHeaderField();
        if ("req".equals(type)){
            messageHeaderField.setOriFieldEnName("输入");
        } else if ("rsp".equals(type)) {
            messageHeaderField.setOriFieldEnName("输出");
        } else {
            logger.error("输入的类型有误："+type);
            return null;
        }
        list.add(messageHeaderField);
        QueryWrapper<MessageHeaderField> messageHeaderFieldQueryWrapper = Wrappers.query();
        messageHeaderFieldQueryWrapper.eq("message_header_id", id);
        messageHeaderFieldQueryWrapper.eq("field_type", type);
        messageHeaderFieldQueryWrapper.orderByAsc("sort");
        List<MessageHeaderField> messageHeaderFieldList = messageHeaderFieldMapper.selectList(messageHeaderFieldQueryWrapper);
        list.addAll(messageHeaderFieldList);
        return list;
    }

    private List<MessageHeaderField> parseExcelToField(List<String> excelContentList, String id) {
        List<MessageHeaderField> messageHeaderFieldList = new ArrayList<>();
        String fileType = null;
        int sort = 1;
        for (int i = 0; i < excelContentList.size(); i++) {
            String content = excelContentList.get(i);
            logger.info("正在处理行内容："+content);
            if ("输入|$||$||$||$||$||$||$||$||$||$||$||$||$|".equals(content)){
                //判断该行是否是输入
                fileType = "req";

            } else if ("输出|$||$||$||$||$||$||$||$||$||$||$||$||$|".equals(content)){
                //判断该行是否是输出
                fileType = "rsp";
            } else {
                //将行内容拆分成数组
                String[] arr = content.split("\\|\\$\\|");
                logger.info("正在处理行内容对应数组长度为："+arr.length);
                MessageHeaderField messageHeaderField =  new MessageHeaderField();
                messageHeaderField = (MessageHeaderField) FillUtil.fill(messageHeaderField);
                messageHeaderField.setMessageHeaderId(id);
                messageHeaderField.setFieldType(fileType);
                messageHeaderField.setSort(sort);
                sort++;
                //原始接口字段
                messageHeaderField.setOriFieldEnName(arr[0]);
                messageHeaderField.setOriFieldCnName(arr[1]);
                messageHeaderField.setOriFieldDataType(arr[2]);
                messageHeaderField.setOriFieldLength(arr[3]);
                messageHeaderField.setOriFieldRequired(arr[4]);
                messageHeaderField.setOriFieldRemarks(arr[5]);
                //QZBSD字段
                messageHeaderField.setBsdFieldEnName(arr[7]);
                messageHeaderField.setBsdFieldCnName(arr[8]);
                messageHeaderField.setBsdFieldDataInfo(arr[9]);
                messageHeaderField.setBsdFieldConstraints(arr[10]);
                messageHeaderField.setBsdFieldRequired(arr[11]);
                //字段没备注时，数组长度为12，长度12时，忽略备注字段，防止数组越界报错
                if (arr.length>=13)
                    messageHeaderField.setBsdFieldRemarks(arr[12]);
                else
                    messageHeaderField.setBsdFieldRemarks("");
                messageHeaderFieldList.add(messageHeaderField);
            }
        }
        return messageHeaderFieldList;
    }

    //判断该报文头id是否存在
    private boolean msgHeaderIdExists(String id){
        MessageHeader messageHeader = messageHeaderMapper.selectById(id);
        if (messageHeader != null)
            return true;
        else
            return false;
    }

    //获取报文头文件的内容
    private List<String> getFileContent(MultipartFile file) {
        logger.info("获取报文头文件内容开始");
        List<String> result = new ArrayList<>();
        InputStream is = null;
        Workbook wb = null;
        Sheet sheet;
        Row row;
        try {
            is = file.getInputStream();
            wb = new XSSFWorkbook(is);
            sheet = wb.getSheetAt(0);
            //获取行数
            int rowNum = sheet.getPhysicalNumberOfRows();
            //从第三行开始
            for (int i = 2; i < rowNum; i++) {
                row = sheet.getRow(i);
                if (row != null) {
                    int cellNum = row.getPhysicalNumberOfCells();
                    StringBuffer sb = new StringBuffer();
                    for (int j = 0; j < cellNum; j++) {
                        Cell cell = row.getCell(j);
                        if (cell != null) {
                            if (cell.getCellType() == CellType.NUMERIC) {
                                //文档中的数字一般都是正整数，但是Excel读取后是double类型，所以一律强转成int型
                                sb.append((int)cell.getNumericCellValue());
                            } else
                                sb.append(cell.getRichStringCellValue().getString());
                        }
                        //每一列的内容用|$|分割并拼接
                        sb.append("|$|");
                    }
                    //将每一行拼接的内容存入列表中
                    result.add(sb.toString());
                }
            }
            logger.info("获取报文头文件内容结束");
            return result;
        } catch (Exception e) {
            logger.error("获取报文头文件内容报错："+e.getMessage());
            e.printStackTrace();
            return null;
        } finally {
            if (wb != null) {
                try {
                    wb.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) {
        String content = "MESSAGE_CODE|$|报文代码|$|STRING|$|6|$|Y|$|核心系统必输|$||$|MESSAGE_CODE|$|报文代码,需要服务系统支持|$|STRING(6)|$|SYS_HEAD|$|N|$||$|";
        String[] arr = content.split("\\|\\$\\|");
        System.out.println(arr.length);
        for (int i = 0; i < arr.length; i++) {
            System.out.println(i+"-"+arr[i]);
        }
    }
}
